<?php


class wxpayrefund {
    protected $values=array();
    private $SSLCERT_PATH;
    private  $SSLKEY_PATH;
    private $parse_array=array();
    private $return_array=array(
        'error'=>false,
        'error_msg'=>''
    );

    //微信订单号，交易总金额，退款金额，退款单号，商户订单号
    public function __construct($transaction_id,$total_fee,$refund_fee,$out_refund_no){
        $this->values['transaction_id']=$transaction_id;
        $this->values['total_fee']=$total_fee;
        $this->values['refund_fee']=$refund_fee;
        $this->values['out_refund_no']=$out_refund_no;
        //$this->values['out_trade_no']=$out_trade_no;
    }

    public function refund(){
        $url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
        $this->SetOp_user_id(Yii::app()->params['mch_id']);
        //$this->SetOut_refund_no();
        $this->SetAppid(Yii::app()->params['APPID']);
        $this->setMch_id(Yii::app()->params['mch_id']);
        $this->SetNonce_str($this->getNonceStr());
        $this->setSign();

        $xml=$this->ToXml();

        $response=$this->postXmlCurl($xml,$url,true,6);

        $this->FromXml($response);

        if($this->values['return_code'] == 'SUCCESS' && $this->values['result_code']=='SUCCESS'){
            if($this->CheckSign()){
                $this->return_array=array(
                    'error'=>false,
                    'error_msg'=>'退款成功',
                );
                return $this->return_array;
            }else{
                $this->return_array=array(
                    'error'=>true,
                    'error_msg'=>'数据签名有误',
                    'data'=>$this->values
                );
                return $this->return_array;
            }
        }else{
            $this->return_array=array(
                'error'=>true,
                'error_msg'=>'退款失败',
                'data'=>$this->values
            );
            return $this->return_array;
        }
    }

    /*protected function SetOut_refund_no(){
        $this->values['out_refund_no']=Yii::app()->params['mch_id'].date("YmdHis");
    }*/
    protected function SetAppid($appid){
        $this->values['appid']=$appid;
    }

    protected function setMch_id($mch_id){
        $this->values['mch_id']=$mch_id;
    }

    protected function SetNonce_str($value){
        $this->values['nonce_str']=$value;
    }


    protected function SetOp_user_id($op_user_id){
        $this->values['op_user_id']=$op_user_id;
    }

    protected function setSign(){
        $sign=$this->makesign();
        $this->values['sign']=$sign;
    }

    //转化为xml
    public function ToXml()
    {
        if(!is_array($this->values) || count($this->values) <= 0)
        {
            $this->return_array=array(
                'error'=>true,
                'error_msg'=>'数组数据异常!'
            );
            return $this->return_array;//返回数据这边如何返回
        }

        $xml = "<xml>";
        foreach ($this->values as $key=>$val)
        {
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";

        return $xml;
    }

    //将XML转化为array
    public function FromXml($xml)
    {
        if(!$xml){
            $this->return_array=array(
                'error'=>true,
                'error_msg'=>'xml数据异常!'
            );
            return $this->return_array;
        }
        libxml_disable_entity_loader(true);
        $this->values = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
    }

    //验证签名
    public function CheckSign()
    {
        if(!array_key_exists('sign', $this->values)){
            return false;
        }
        $sign = $this->MakeSign();
        if($this->values['sign']== $sign){
            return true;
        }else{
            return false;
        }
    }

    //产生随机字符串
    public function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }
    //生成签名
    public  function makesign(){

        //签名步骤一：按字典序排序参数
        ksort($this->values);

        $string = $this->ToUrlParams();
        //签名步骤二：在string后加入KEY
        $string = $string . "&key=".Yii::app()->params['weixin_key'];
        //签名步骤三：MD5加密
        $string = md5($string);
        //签名步骤四：所有字符转为大写
        $result = strtoupper($string);

        return $result;
    }

    /**
     * 格式化参数格式化成url参数
     */
    public function ToUrlParams()
    {
        $buff = "";
        foreach ($this->values as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }


    private  function setSSLCERT_PATH(){
        $this->SSLCERT_PATH=$_SERVER['DOCUMENT_ROOT']."/protected/extensions/weixin/apiclient_cert.pem";
    }

    private  function setSSLKEY_PATH(){
        $this->SSLKEY_PATH=$_SERVER['DOCUMENT_ROOT']."/protected/extensions/weixin/apiclient_key.pem";
    }

    /**
     * 以post方式提交xml到对应的接口url
     *
     * @param string $xml  需要post的xml数据
     * @param string $url  url
     * @param bool $useCert 是否需要证书，默认不需要
     * @param int $second   url执行超时时间，默认30s
     * @throws WxPayException
     */
    private  function postXmlCurl($xml, $url, $useCert = false, $second = 30)
    {
        $ch = curl_init();
        //设置超时
        curl_setopt($ch, CURLOPT_TIMEOUT, $second);


        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);
        //设置header
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        //要求结果为字符串且输出到屏幕上
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);

        if($useCert == true){
            //设置证书
            $this->setSSLCERT_PATH();
            $this->setSSLKEY_PATH();
            //使用证书：cert 与 key 分别属于两个.pem文件
            curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLCERT, $this->SSLCERT_PATH);
            curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');
            curl_setopt($ch,CURLOPT_SSLKEY, $this->SSLKEY_PATH);
        }
        //post提交方式
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        //运行curl
        $data = curl_exec($ch);
        //返回结果
        if($data){
            curl_close($ch);
            return $data;
        } else {
            $error = curl_errno($ch);
            curl_close($ch);
            $this->return_array=array(
                'error'=>true,
                'error_msg'=>"curl出错，错误码:$error"
            );
            return $this->return_array;
        }
    }
} 